home *** CD-ROM | disk | FTP | other *** search
/ Delphi Informant Complete 1995 - 2000 / Delphi Informant Complete 1995 to 2000.iso / Delphi Informant Magazine Complete Works SOURCE CODE 1998.rar / 1998 / May / di9805rs / Llist.pas < prev    next >
Pascal/Delphi Source File  |  1997-12-31  |  6KB  |  226 lines

  1. unit LList;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Graphics, Controls,
  7.   Forms, Dialogs, Menus, StdCtrls, Classes;
  8.  
  9. type
  10.     // The linked list cells.
  11.     PCell = ^TCell;
  12.     TCell = record
  13.         Value    : String[20]; // The data.
  14.         NextCell : PCell;      // The next cell in the list.
  15.     end;
  16.  
  17.   TLinkedListForm = class(TForm)
  18.     ValueText: TEdit;
  19.     CmdInsertAfter: TButton;
  20.     CmdRemoveAfter: TButton;
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure CmdInsertAfterClick(Sender: TObject);
  23.     procedure CmdRemoveAfterClick(Sender: TObject);
  24.     procedure ValueTextChange(Sender: TObject);
  25.     procedure DrawList;
  26.     procedure FormPaint(Sender: TObject);
  27.     procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
  28.       Shift: TShiftState; X, Y: Integer);
  29.     procedure EnableButtons;
  30.     procedure FormDestroy(Sender: TObject);
  31.   private
  32.     { Private declarations }
  33.     sentinel  : TCell;
  34.     num_items : Integer; // For convenience.
  35.     selected  : Integer; // Selected cell index. 0 = sentinel.
  36.   public
  37.     { Public declarations }
  38.   end;
  39.  
  40. var
  41.   LinkedListForm: TLinkedListForm;
  42.  
  43. implementation
  44.  
  45. {$R *.DFM}
  46.  
  47. const
  48.     HGT = 14;
  49.     GAP = 3;
  50.  
  51. // Initialize the empty linked list.
  52. procedure TLinkedListForm.FormCreate(Sender: TObject);
  53. begin
  54.     sentinel.NextCell := nil;
  55.     sentinel.Value := '<sentinel>';
  56.     num_items := 0;
  57.  
  58.     // Start with no item selected.
  59.     selected := -1;
  60. end;
  61.  
  62. // Add a new cell after the selected cell.
  63. procedure TLinkedListForm.CmdInsertAfterClick(Sender: TObject);
  64. var
  65.     after_me, new_cell : PCell;
  66.     i                  : Integer;
  67. begin
  68.     // Find the insertion position.
  69.     after_me := @sentinel;
  70.     for i := 1 to selected do
  71.         after_me := after_me^.NextCell;
  72.  
  73.     // Create the new cell.
  74.     New(new_cell);
  75.     new_cell^.Value := ValueText.Text;
  76.  
  77.     // Insert the cell in the list.
  78.     new_cell^.NextCell := after_me^.NextCell;
  79.     after_me^.NextCell := new_cell;
  80.     num_items := num_items + 1;
  81.  
  82.     // Select the new cell and redisplay the list.
  83.     selected := selected + 1;
  84.     DrawList;
  85.     EnableButtons;
  86.  
  87.     ValueText.Text := '';
  88.     ValueText.SetFocus;
  89. end;
  90.  
  91. // Remove the cell after the selected cell.
  92. procedure TLinkedListForm.CmdRemoveAfterClick(Sender: TObject);
  93. var
  94.     after_me, target : PCell;
  95.     i                : Integer;
  96. begin
  97.     // Find the cell before the target cell.
  98.     after_me := @sentinel;
  99.     for i := 1 to selected do
  100.         after_me := after_me^.NextCell;
  101.  
  102.     // Remove the next cell from the list.
  103.     target := after_me^.NextCell;
  104.     after_me^.NextCell := target^.NextCell;
  105.  
  106.     // Free the target cell's memory.
  107.     Dispose(target);
  108.     num_items := num_items - 1;
  109.  
  110.     // Redisplay the list.
  111.     DrawList;
  112.     EnableButtons;
  113.     ValueText.SetFocus;
  114. end;
  115.  
  116. // Enable the appropriate buttons.
  117. procedure TLinkedListForm.ValueTextChange(Sender: TObject);
  118. begin
  119.     CmdInsertAfter.Enabled := ((selected >= 0) and
  120.         (ValueText.Text <> ''));
  121. end;
  122.  
  123. // Display the list, highlighting the selected item.
  124. procedure TLinkedListForm.DrawList;
  125. var
  126.     cell_ptr : PCell;
  127.     i, x, y  : Integer;
  128.     rect     : TRect;
  129. begin
  130.     // Clear the form.
  131.     rect.Left := 0;
  132.     rect.Top := 0;
  133.     rect.Right := ClientWidth;
  134.     rect.Bottom := ClientHeight;
  135.     Canvas.Brush.Color := clLtGray;
  136.     Canvas.FillRect(rect);
  137.  
  138.     // Display the list items.
  139.     x := ValueText.Left + ValueText.Width + 5;
  140.     y := ValueText.Top;
  141.     rect.Left := x;
  142.     rect.Right := ClientWidth;
  143.     cell_ptr := @sentinel;
  144.     for i := 0 to num_items do
  145.     begin
  146.         if (i = selected) then
  147.         begin
  148.             Canvas.Brush.Color := clBlack;
  149.             Canvas.Font.Color := clLtGray;
  150.         end else begin
  151.             Canvas.Brush.Color := clLtGray;
  152.             Canvas.Font.Color := clBlack;
  153.         end;
  154.         // Fill in the item's background.
  155.         rect.Top := y;
  156.         rect.Bottom := y + HGT;
  157.         Canvas.FillRect(rect);
  158.  
  159.         // Display the text.
  160.         Canvas.TextOut(x, y, cell_ptr^.Value);
  161.         y := y + HGT + GAP;
  162.  
  163.         // Move to the next cell.
  164.         cell_ptr := cell_ptr^.NextCell;
  165.     end;
  166. end;
  167.  
  168. // Redraw the list.
  169. procedure TLinkedListForm.FormPaint(Sender: TObject);
  170. begin
  171.     DrawList;
  172. end;
  173.  
  174. // Select the item clicked.
  175. procedure TLinkedListForm.FormMouseUp(Sender: TObject;
  176.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  177. var
  178.     i : Longint;
  179. begin
  180.     // Do nothing if the mouse is too far left.
  181.     if ((X < ValueText.Left + ValueText.Width + 5) or
  182.         (Y < ValueText.Top))
  183.     then
  184.         selected := -1
  185.     else begin
  186.         // See which item number it is.
  187.         i := (y - ValueText.Top) div (HGT + GAP);
  188.         if ((i >= 0) and (i <= num_items)) then
  189.             selected := i
  190.         else
  191.             selected := -1;
  192.     end;
  193.  
  194.     // Redraw the list.
  195.     DrawList;
  196.  
  197.     // Enable the appropriate buttons.
  198.     EnableButtons;
  199. end;
  200.  
  201. procedure TLinkedListForm.EnableButtons;
  202. begin
  203.     CmdInsertAfter.Enabled := ((selected >= 0) and
  204.         (ValueText.Text <> ''));
  205.     CmdRemoveAfter.Enabled := ((selected >= 0) and
  206.         (selected < num_items));
  207. end;
  208.  
  209. // Free all the linked list memory.
  210. // This doesn't matter for this example program. It would
  211. // be important if the program created and destroyed
  212. // many forms.
  213. procedure TLinkedListForm.FormDestroy(Sender: TObject);
  214. var
  215.     target : PCell;
  216. begin
  217.     while (sentinel.NextCell <> nil) do
  218.     begin
  219.         target := sentinel.NextCell;
  220.         sentinel.NextCell := target^.NextCell;
  221.         Dispose(target);
  222.     end;
  223. end;
  224.  
  225. end.
  226.